/**
 * 图片识别功能模块
 * 提供图片拍照、选择、压缩、识别等功能
 */

class ImageRecognition {
    constructor() {
        this.maxImageSize = 1024 * 1024; // 1MB
        this.maxImageWidth = 800;
        this.maxImageHeight = 600;
        this.supportedFormats = ['image/jpeg', 'image/png', 'image/webp'];
        this.debug = true;
    }

    log(...args) {
        if (this.debug) {
            console.log('[ImageRecognition]', ...args);
        }
    }

    /**
     * 调试日志
     * @param {string} message 日志消息
     */
    log(message) {
        if (this.debug) {
            console.log('[ImageRecognition]', message);
        }
    }

    /**
     * 检查环境支持
     * @returns {Object} 支持情况
     */
    checkEnvironment() {
        const env = {
            plus: !!(window.plus),
            camera: !!(window.plus && plus.camera),
            gallery: !!(window.plus && plus.gallery),
            canvas: !!(document.createElement('canvas').getContext),
            fileReader: !!(window.FileReader),
            eventSource: !!(window.EventSource)
        };
        
        this.log('环境检查结果:', env);
        return env;
    }

    /**
     * 拍照功能
     * @param {Function} onSuccess 成功回调
     * @param {Function} onError 错误回调
     */
    takePhoto(onSuccess, onError) {
        this.log('开始拍照...');
        
        const env = this.checkEnvironment();
        if (!env.plus) {
            const error = '当前环境不支持原生API，请使用相册选择功能';
            this.log(error);
            onError && onError(error);
            return;
        }

        if (!env.camera) {
            const error = '设备不支持拍照功能';
            this.log(error);
            onError && onError(error);
            return;
        }

        try {
            plus.camera.getCamera().captureImage((path) => {
                this.log('拍照成功，路径:', path);
                this.processImage(path, 'camera', onSuccess, onError);
            }, (error) => {
                const errorMsg = '拍照失败：' + (error.message || error);
                this.log(errorMsg);
                onError && onError(errorMsg);
            }, {
                filename: '_doc/camera/',
                index: 1
            });
        } catch (error) {
            const errorMsg = '拍照异常：' + error.message;
            this.log(errorMsg);
            onError && onError(errorMsg);
        }
    }

    /**
     * 从相册选择图片
     * @param {Function} onSuccess 成功回调
     * @param {Function} onError 错误回调
     */
    selectFromGallery(onSuccess, onError) {
        this.log('开始选择图片...');
        
        const env = this.checkEnvironment();
        if (env.plus && env.gallery) {
            try {
                plus.gallery.pick((path) => {
                    this.log('相册选择成功，路径:', path);
                    this.processImage(path, 'gallery', onSuccess, onError);
                }, (error) => {
                    const errorMsg = '选择图片失败：' + (error.message || error);
                    this.log(errorMsg);
                    onError && onError(errorMsg);
                }, {
                    filter: 'image',
                    multiple: false
                });
            } catch (error) {
                const errorMsg = '相册选择异常：' + error.message;
                this.log(errorMsg);
                onError && onError(errorMsg);
            }
        } else {
            this.log('原生相册不可用，使用文件输入');
            this.selectFromFileInput(onSuccess, onError);
        }
    }

    /**
     * 从文件输入选择图片（Web环境）
     * @param {Function} onSuccess 成功回调
     * @param {Function} onError 错误回调
     */
    selectFromFileInput(onSuccess, onError) {
        this.log('使用文件输入选择图片');
        
        if (!this.checkEnvironment().fileReader) {
            const error = '浏览器不支持文件读取功能';
            this.log(error);
            onError && onError(error);
            return;
        }

        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = 'image/*';
        fileInput.onchange = (e) => {
            const file = e.target.files[0];
            if (file) {
                this.log('文件选择成功:', file.name, '大小:', file.size);
                this.validateAndProcessFile(file, onSuccess, onError);
            } else {
                const error = '未选择文件';
                this.log(error);
                onError && onError(error);
            }
        };
        fileInput.click();
    }

    /**
     * 校验并处理图片文件（兼容H5和DCloud原生环境）
     * @param {File|string} file File对象或file:///路径
     * @param {Function} onSuccess 成功回调
     * @param {Function} onError 失败回调
     */
    validateAndProcessFile(file, onSuccess, onError) {
        this.log('validateAndProcessFile typeof:', typeof file, file);
        if (!file) {
            const error = '未选择图片文件';
            this.log(error);
            onError && onError(error);
            return;
        }
        // 检查文件大小（仅File对象有size属性）
        if (file.size && file.size > this.maxImageSize) {
            const error = `图片文件过大: ${(file.size / 1024 / 1024).toFixed(2)}MB，请选择小于 1MB 的图片`;
            this.log(error);
            onError && onError(error);
            return;
        }
        // DCloud原生环境：file为字符串路径
        if (typeof file === 'string' && file.startsWith('file://')) {
            plus.io.resolveLocalFileSystemURL(file, (entry) => {
                entry.file((fileObj) => {
                    var reader = new FileReader();
                    reader.onload = (e) => {
                        this.log('文件读取成功，开始压缩');
                        this.compressImage(e.target.result, onSuccess, onError);
                    };
                    reader.onerror = (error) => {
                        const errorMsg = '读取图片文件失败: ' + error.message;
                        this.log(errorMsg);
                        onError && onError(errorMsg);
                    };
                    reader.readAsDataURL(fileObj);
                }, (error) => {
                    const errorMsg = '获取File对象失败: ' + error.message;
                    this.log(errorMsg);
                    onError && onError(errorMsg);
                });
            }, (error) => {
                const errorMsg = '解析文件路径失败: ' + error.message;
                this.log(errorMsg);
                onError && onError(errorMsg);
            });
        } else {
            // H5 File/Blob
            var reader = new FileReader();
            reader.onload = (e) => {
                this.log('文件读取成功，开始压缩');
                this.compressImage(e.target.result, onSuccess, onError);
            };
            reader.onerror = (error) => {
                const errorMsg = '读取图片文件失败: ' + error.message;
                this.log(errorMsg);
                onError && onError(errorMsg);
            };
            reader.readAsDataURL(file);
        }
    }

    /**
     * 处理原生图片路径（兼容H5和DCloud原生环境）
     * @param {string} path 图片路径
     * @param {string} source 来源
     * @param {Function} onSuccess 成功回调
     * @param {Function} onError 失败回调
     */
    processImage(path, source, onSuccess, onError) {
        this.log('processImage 路径:', path, '来源:', source);
        if (source === 'file') {
            this.compressImage(path, onSuccess, onError);
        } else if (typeof path === 'string' && path.startsWith('file://')) {
            // DCloud原生路径，先转File对象
            plus.io.resolveLocalFileSystemURL(path, (entry) => {
                entry.file((fileObj) => {
                    var reader = new FileReader();
                    reader.onload = (e) => {
                        this.log('原生文件读取成功');
                        this.compressImage(e.target.result, onSuccess, onError);
                    };
                    reader.onerror = (error) => {
                        const errorMsg = '读取图片文件失败: ' + error.message;
                        this.log(errorMsg);
                        onError && onError(errorMsg);
                    };
                    reader.readAsDataURL(fileObj);
                }, (error) => {
                    const errorMsg = '获取File对象失败: ' + error.message;
                    this.log(errorMsg);
                    onError && onError(errorMsg);
                });
            }, (error) => {
                const errorMsg = '解析文件路径失败: ' + error.message;
                this.log(errorMsg);
                onError && onError(errorMsg);
            });
        } else {
            // H5 base64
            this.compressImage(path, onSuccess, onError);
        }
    }

    /**
     * 压缩图片
     * @param {string} imageData 图片数据（base64）
     * @param {Function} onSuccess 成功回调
     * @param {Function} onError 错误回调
     */
    compressImage(imageData, onSuccess, onError) {
        this.log('开始压缩图片...');

        if (!this.checkEnvironment().canvas) {
            const error = '浏览器不支持Canvas功能';
            this.log(error);
            onError && onError(error);
            return;
        }

        const img = new Image();
        img.onload = () => {
            this.log('图片加载成功，原始尺寸:', img.width, 'x', img.height);
            
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');

            // 计算压缩后的尺寸
            let { width, height } = this.calculateDimensions(img.width, img.height);
            this.log('压缩后尺寸:', width, 'x', height);

            canvas.width = width;
            canvas.height = height;

            // 绘制压缩后的图片
            ctx.drawImage(img, 0, 0, width, height);

            // 转换为base64，使用较低的质量
            const compressedData = canvas.toDataURL('image/jpeg', 0.8);
            const compressedSize = (compressedData.length / 1024).toFixed(2);
            this.log('压缩完成，大小:', compressedSize, 'KB');

            onSuccess && onSuccess(compressedData);
        };
        img.onerror = (error) => {
            const errorMsg = '图片加载失败: ' + error.message;
            this.log(errorMsg);
            onError && onError(errorMsg);
        };
        img.src = imageData;
    }

    /**
     * 计算压缩后的尺寸
     * @param {number} originalWidth 原始宽度
     * @param {number} originalHeight 原始高度
     * @returns {Object} 压缩后的尺寸
     */
    calculateDimensions(originalWidth, originalHeight) {
        let width = originalWidth;
        let height = originalHeight;

        // 如果图片尺寸超过限制，按比例缩小
        if (width > this.maxImageWidth || height > this.maxImageHeight) {
            const ratio = Math.min(this.maxImageWidth / width, this.maxImageHeight / height);
            width = Math.round(width * ratio);
            height = Math.round(height * ratio);
        }

        return { width, height };
    }

    /**
     * 发送图片到AI进行识别
     * @param {string} imageData 图片数据
     * @param {string} userId 用户ID
     * @param {string} baseUrl 基础URL
     * @param {Function} onMessage 消息回调
     * @param {Function} onError 错误回调
     * @param {Function} onClose 关闭回调
     */
    sendImageToAI(imageData, userId, baseUrl, onMessage, onError, onClose) {
        this.log('开始发送图片到AI...');
        this.log('用户ID:', userId);
        this.log('基础URL:', baseUrl);

        if (!this.checkEnvironment().eventSource) {
            const error = '浏览器不支持EventSource功能';
            this.log(error);
            onError && onError(error);
            return null;
        }

        if (!baseUrl) {
            const error = 'API地址未配置';
            this.log(error);
            onError && onError(error);
            return null;
        }

        try {
            const url = `${baseUrl}/api/chat/image?userId=${userId}&imageData=${encodeURIComponent(imageData)}`;
            this.log('发送请求到:', url);

            const eventSource = new EventSource(url);

            eventSource.onopen = () => {
                this.log('EventSource连接已建立');
            };

            eventSource.onmessage = (event) => {
                this.log('收到AI回复:', event.data);
                onMessage && onMessage(event.data);
            };

            eventSource.onerror = (err) => {
                this.log('EventSource错误:', err);
                eventSource.close();
                const errorMsg = '图片识别连接失败，请检查网络连接和服务器状态';
                this.log(errorMsg);
                onError && onError(errorMsg);
            };

            // 返回eventSource以便外部控制
            return eventSource;
        } catch (error) {
            const errorMsg = '图片识别连接失败：' + error.message;
            this.log(errorMsg);
            onError && onError(errorMsg);
            return null;
        }
    }

    /**
     * 保存图片聊天记录
     * @param {Object} data 聊天数据
     * @param {Function} onSuccess 成功回调
     * @param {Function} onError 错误回调
     */
    saveImageChatRecord(data, onSuccess, onError) {
        this.log('保存图片聊天记录:', data);
        
        // 这里可以调用您的request模块来保存聊天记录
        if (window.request && window.request.post) {
            window.request.post("/system/chatMessages", data, onSuccess, onError);
        } else {
            const error = '请求模块未加载';
            this.log(error);
            onError && onError(error);
        }
    }

    /**
     * 检查设备是否支持拍照
     * @returns {boolean} 是否支持
     */
    isCameraSupported() {
        const supported = !!(plus && plus.camera);
        this.log('摄像头支持检查:', supported);
        return supported;
    }

    /**
     * 检查设备是否支持相册
     * @returns {boolean} 是否支持
     */
    isGallerySupported() {
        const supported = !!(plus && plus.gallery);
        this.log('相册支持检查:', supported);
        return supported;
    }

    /**
     * 获取支持的图片格式
     * @returns {Array} 支持的格式列表
     */
    getSupportedFormats() {
        return this.supportedFormats;
    }

    /**
     * 获取最大图片尺寸
     * @returns {number} 最大尺寸（字节）
     */
    getMaxImageSize() {
        return this.maxImageSize;
    }

    /**
     * 启用/禁用调试模式
     * @param {boolean} enabled 是否启用
     */
    setDebugMode(enabled) {
        this.debug = enabled;
        this.log('调试模式:', enabled ? '启用' : '禁用');
    }

    /**
     * 快速诊断图片识别功能
     * @returns {Object} 诊断结果
     */
    diagnose() {
        this.log('开始诊断图片识别功能...');
        
        const diagnosis = {
            timestamp: new Date().toISOString(),
            environment: this.checkEnvironment(),
            configuration: {
                baseUrl: localStorage.getItem("ip"),
                backend: localStorage.getItem("backend"),
                userId: localStorage.getItem("userId"),
                token: localStorage.getItem("token") ? '已设置' : '未设置'
            },
            issues: []
        };

        // 检查环境问题
        if (!diagnosis.environment.plus) {
            diagnosis.issues.push('Plus API不可用 - 可能不在原生环境中运行');
        }
        if (!diagnosis.environment.camera && !diagnosis.environment.gallery) {
            diagnosis.issues.push('摄像头和相册都不可用 - 可能缺少权限或不在原生环境');
        }
        if (!diagnosis.environment.canvas) {
            diagnosis.issues.push('Canvas不可用 - 图片压缩功能将无法工作');
        }
        if (!diagnosis.environment.fileReader) {
            diagnosis.issues.push('FileReader不可用 - 文件读取功能将无法工作');
        }
        if (!diagnosis.environment.eventSource) {
            diagnosis.issues.push('EventSource不可用 - AI识别功能将无法工作');
        }

        // 检查配置问题
        if (!diagnosis.configuration.baseUrl) {
            diagnosis.issues.push('API地址未配置');
        }
        if (!diagnosis.configuration.userId) {
            diagnosis.issues.push('用户ID未设置');
        }
        if (!navigator.onLine) {
            diagnosis.issues.push('网络连接异常');
        }

        this.log('诊断完成:', diagnosis);
        return diagnosis;
    }

    // 新增：POST文件并流式解析SSE响应
    sendImageToAIStream(file, question, onMessage, onError) {
        const baseUrl = localStorage.getItem("ip");
        console.log('[图片识别调试] baseUrl:', baseUrl);
        if (!baseUrl) {
            onError && onError("API地址未配置");
            return;
        }
        const url = baseUrl + "/api/image/recognize/stream";
        console.log('[图片识别调试] url:', url);
        console.log('[图片识别调试] file:', file);
        console.log('[图片识别调试] question:', question);
        const formData = new FormData();
        formData.append("file", file);
        if (question) formData.append("question", question);
        // 打印FormData内容
        for (let pair of formData.entries()) {
            console.log('[图片识别调试] formData:', pair[0], pair[1]);
        }
        const token = localStorage.getItem('token');
        const headers = token ? { 'Authorization': token } : {};
        fetch(url, { method: "POST", body: formData, headers })
            .then(response => {
                console.log('[图片识别调试] fetch response:', response);
                console.log('[图片识别调试] fetch status:', response.status);

                const contentType = response.headers.get('content-type') || '';
                if (response.status !== 200 || !contentType.includes('text/event-stream')) {
                    response.text().then(text => {
                        console.log('[图片识别调试] fetch response text:', text);
                        onError && onError('图片识别请求失败: ' + text);
                    });
                    return;
                }

                if (!response.body) {
                    onError && onError("浏览器不支持流式响应");
                    return;
                }
                const reader = response.body.getReader();
                let decoder = new TextDecoder("utf-8");
                let buffer = "";
                function read() {
                    reader.read().then(({ done, value }) => {
                        if (done) return;
                        buffer += decoder.decode(value, { stream: true });
                        let lines = buffer.split("\n");
                        buffer = lines.pop();
                        for (let line of lines) {
                            if (line.startsWith("data:")) {
                                let data = line.replace(/^data:\s*/, "");
                                onMessage && onMessage(data);
                            }
                        }
                        read();
                    });
                }
                read();
            })
            .catch(err => {
                console.error('[图片识别调试] fetch error:', err);
                onError && onError("图片识别请求失败: " + err.message);
            });
    }

    // 新增：AI对话流式接口
    sendChatToAIStream(question, userId, onMessage, onError) {
        const baseUrl = localStorage.getItem("ip");
        if (!baseUrl) {
            onError && onError("API地址未配置");
            return;
        }
        const url = baseUrl + "/api/deepseek/chat/stream";
        const formData = new FormData();
        formData.append("question", question);
        formData.append("userId", userId);
        const token = localStorage.getItem('token');
        const headers = token ? { 'Authorization': token } : {};
        fetch(url, { method: "POST", body: formData, headers })
            .then(response => {
                const contentType = response.headers.get('content-type') || '';
                if (response.status !== 200 || !contentType.includes('text/event-stream')) {
                    response.text().then(text => {
                        onError && onError('AI对话请求失败: ' + text);
                    });
                    return;
                }
                if (!response.body) {
                    onError && onError("浏览器不支持流式响应");
                    return;
                }
                const reader = response.body.getReader();
                let decoder = new TextDecoder("utf-8");
                let buffer = "";
                function read() {
                    reader.read().then(({ done, value }) => {
                        if (done) {
                            if (typeof window.finishAssistantMessage === 'function') {
                                window.finishAssistantMessage();
                            }
                            return;
                        }
                        buffer += decoder.decode(value, { stream: true });
                        let lines = buffer.split("\n");
                        buffer = lines.pop();
                        for (let line of lines) {
                            if (line.startsWith("data:")) {
                                let data = line.replace(/^data:\s*/, "");
                                onMessage && onMessage(data);
                            }
                        }
                        read();
                    });
                }
                read();
            })
            .catch(err => {
                onError && onError("AI对话请求失败: " + err.message);
            });
    }

    // 选择图片（Web环境）直接返回File对象
    selectFromFileInput(onSuccess, onError) {
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = 'image/*';
        fileInput.onchange = (e) => {
            const file = e.target.files[0];
            if (file) {
                if (!this.supportedFormats.includes(file.type)) {
                    onError && onError('不支持的图片格式，请选择 JPG、PNG 或 WebP 格式的图片');
                    return;
                }
                if (file.size > this.maxImageSize) {
                    onError && onError('图片文件过大，请选择小于 1MB 的图片');
                    return;
                }
                onSuccess && onSuccess(file);
            } else {
                onError && onError('未选择文件');
            }
        };
        fileInput.click();
    }

    // 选择图片（原生环境）直接返回File对象
    selectFromGallery(onSuccess, onError) {
        if (window.plus && plus.gallery) {
            plus.gallery.pick((path) => {
                plus.io.resolveLocalFileSystemURL(path, (entry) => {
                    entry.file((file) => {
                        onSuccess && onSuccess(file);
                    }, (e) => {
                        onError && onError('读取图片文件失败: ' + e.message);
                    });
                }, (e) => {
                    onError && onError('解析文件路径失败: ' + e.message);
                });
            }, (error) => {
                onError && onError('选择图片失败: ' + (error.message || error));
            }, {
                filter: 'image',
                multiple: false
            });
        } else {
            this.selectFromFileInput(onSuccess, onError);
        }
    }

    // 拍照（原生环境）直接返回File对象
    takePhoto(onSuccess, onError) {
        if (window.plus && plus.camera) {
            plus.camera.getCamera().captureImage((path) => {
                plus.io.resolveLocalFileSystemURL(path, (entry) => {
                    entry.file((file) => {
                        onSuccess && onSuccess(file);
                    }, (e) => {
                        onError && onError('读取图片文件失败: ' + e.message);
                    });
                }, (e) => {
                    onError && onError('解析文件路径失败: ' + e.message);
                });
            }, (error) => {
                onError && onError('拍照失败: ' + (error.message || error));
            }, {
                filename: '_doc/camera/',
                index: 1
            });
        } else {
            onError && onError('设备不支持拍照功能');
        }
    }

    // 兼容性保留：获取支持的图片格式
    getSupportedFormats() {
        return this.supportedFormats;
    }
    getMaxImageSize() {
        return this.maxImageSize;
    }
}
window.imageRecognition = new ImageRecognition(); 